/*
//	CP2013 Traffic Simulator Assignment :: C++ DLL
//	Copyright (c) 2010, Adam Rehn
//
//	This DLL exposes functions to the VB GUI.
*/
#include <windows.h>
#include <Oleauto.h>
#include <Objbase.h>
#include <adam/base.h>
#include <iostream>
#define DLLEXPORT extern "C" __declspec(dllexport)

#include "model/model.h"
#include "controller/controller.h"
#include "view/view.h"

//This is the object that it created and passed to VB
class SimulationInstance
{
	public:
		SimulationInstance();
		~SimulationInstance();
		
		mvcModel* model;
		mvcController* controller;
		mvcView* view;
};

SimulationInstance::SimulationInstance()
{
	//MessageBox(NULL, "Constructor Called.", "Debug", MB_ICONINFORMATION);
	model = NULL;
	controller = NULL;
	view = NULL;
	
	//Due to the way SDL works, we need to initialise it here instead of in the visualisationWindow class
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
		throw "Could not initialise SDL!";
	atexit(SDL_Quit);
	
	//These lines are required for centering the visualisation window when it is created
	putenv("SDL_VIDEO_WINDOW_POS");
	putenv("SDL_VIDEO_CENTERED=1");
	getenv("SDL_VIDEO_WINDOW_POS");
	getenv("SDL_VIDEO_CENTERED");
}

SimulationInstance::~SimulationInstance()
{
	//Delete the Model, View, and Controller
	if (this->controller) delete this->controller;
	if (this->model)      delete this->model;
	if (this->view)       delete this->view;
	SDL_Quit();
	//MessageBox(NULL, "Destructor Called.", "Debug", MB_ICONINFORMATION);
}

DLLEXPORT int toInt(char* v)
{
	return to<int>(v);
}

DLLEXPORT simulationParams* createSetupParams(
	unsigned int lanes_N,
	unsigned int lanes_S,
	unsigned int lanes_E,
	unsigned int lanes_W,
	unsigned int probability_N,
	unsigned int probability_S,
	unsigned int probability_E,
	unsigned int probability_W
)
{
	//Create a new simulationParams instance
	simulationParams* setup = new simulationParams;
	
	setup->lanes_N       = lanes_N;
	setup->lanes_S       = lanes_S;
	setup->lanes_E       = lanes_E;
	setup->lanes_W       = lanes_W;
	setup->probability_N = probability_N;
	setup->probability_S = probability_S;
	setup->probability_E = probability_E;
	setup->probability_W = probability_W;
	
	//Return the instance pointer
	return setup;
}

DLLEXPORT SimulationInstance* createSimulation()
{
	//Create an instance
	SimulationInstance* instance = new SimulationInstance;
	
	//Create a struct and populate it with the simulation parameters
	simulationParams setup;
	setup.lanes_N       = 1;
	setup.lanes_S       = 1;
	setup.lanes_E       = 1;
	setup.lanes_W       = 1;
	setup.probability_N = 0;
	setup.probability_S = 0;
	setup.probability_E = 0;
	setup.probability_W = 0;
	
	//Create the model with the dummy parameters
	instance->model = new mvcModel(setup);

	//Create the controller and bind it to the model
	instance->controller = new mvcController(instance->model);
	
	//Create the view (visualisation) and bind it to the controller
	instance->view = new mvcView();
	instance->controller->addView(instance->view);
	
	//Return the simulation instance pointer
	return instance;
}

DLLEXPORT void startSimulation(SimulationInstance* instance, simulationParams* setup)
{
	if (setup != NULL)
	{
		//Recreate the model with the supplied parameters
		delete instance->model;
		instance->model = new mvcModel(*setup);
		
		//Delete the setup instance
		delete setup;
		
		//Update the view
		instance->view->resetView(instance->model);
		
		//Run the setup
		instance->controller->startSimulation();
	}
}

DLLEXPORT bool runCycle(SimulationInstance* instance)
{
	return instance->controller->runCycle();
}

DLLEXPORT void stopSimulation(SimulationInstance* instance)
{
	instance->controller->stopSimulation();
}

DLLEXPORT void setVisWindowTitle(SimulationInstance* instance, char* title)
{
	instance->view->setVisWindowTitle(title);
}

DLLEXPORT void destroySimulation(SimulationInstance* instance)
{
	//Attempt to delete the supplied instance
	try {
		delete instance;
	} catch (...) {
		//Do nothing
	}
}
